#include <iostream>
#include <vector>
#include <algorithm>
using namespace std;

struct Edge {
  int src;
  int dest;
  int weight;
  Edge(int _src, int _dest, int _weight) : src(_src), dest(_dest), weight(_weight) {}
};

struct Graph {
  int V;
  vector<Edge> edges;
};

struct Subset {
  int parent;
  int rank;
};

bool compareEdges(Edge e1, Edge e2) {
  return e1.weight < e2.weight;
}

int find(Subset subsets[], int i) {
  if (subsets[i].parent != i) {
    subsets[i].parent = find(subsets, subsets[i].parent);
  }
  return subsets[i].parent;
}

void Union(Subset subsets[], int x, int y) {
  int xroot = find(subsets, x);
  int yroot = find(subsets, y);

  if (subsets[xroot].rank < subsets[yroot].rank) {
    subsets[xroot].parent = yroot;
  } else if (subsets[xroot].rank > subsets[yroot].rank) {
    subsets[yroot].parent = xroot;
  } else {
    subsets[yroot].parent = xroot;
    subsets[xroot].rank++;
  }
}

void findMinimumSpanningTree(Graph& graph) {
  vector<Edge> result;
  Subset* subsets = new Subset[graph.V];

  for (int i = 0; i < graph.V; i++) {
    subsets[i].parent = i;
    subsets[i].rank = 0;
  }

  sort(graph.edges.begin(), graph.edges.end(), compareEdges);

  int e = 0, i = 0;

  while (e < graph.V - 1 && i < graph.edges.size()) {
    Edge nextEdge = graph.edges[i++];
    int x = find(subsets, nextEdge.src);
    int y = find(subsets, nextEdge.dest);

    if (x != y) {
      result.push_back(nextEdge);
      Union(subsets, x, y);
      e++;
    }
  }

  cout << "最小生成树的边：" << endl;
  for (auto edge : result) {
    cout << edge.src << " - " << edge.dest << "，权重：" << edge.weight << endl;
  }

  delete[] subsets;
}

int main() {
  int V = 4; 

  Graph graph;
  graph.V = V;

  graph.edges.push_back(Edge(0, 1, 10));
  graph.edges.push_back(Edge(0, 2, 6));
  graph.edges.push_back(Edge(0, 3, 5));
  graph.edges.push_back(Edge(1, 3, 15));
  graph.edges.push_back(Edge(2, 3, 4));

  findMinimumSpanningTree(graph);

  return 0;
}